package com.fuchen.academic.vo;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Pagination<T> {
	
	class Config{
		/**
		 * 指定页面跳转时接收跳转页数的param变量
		 */
		public String page = "page";
		
		/**
		 * 指定跳转的路径
		 */
		public String path = "";
		
		/**
		 * 指定分页时的查询参数
		 */
		public Map<String,String> queryParams = new HashMap<String,String>();
	}
	
	/**
	 * 分页的配置
	 */
	private Config config;
	
	/**
	 * 自定义配置的构造函数
	 * @param currentPage
	 * @param total
	 */
	public Pagination(int currentPage,int total){
		config = new Config();
		this.currentPage = currentPage;
		this.total = total;
		this.lastPage = total % pageSize == 0 ? total/pageSize : (total/pageSize + 1);
		this.hasMore = this.currentPage < this.lastPage;
	}

	public Pagination(int currentPage,int total,Map<String,String> queryParams){
		this(currentPage, total);
		if(null != queryParams){
			config.queryParams = queryParams;
		}
	}
	
	/**
	 * 自定义配置的构造函数
	 * @param page
	 * @param path
	 * @param queryParams
	 */
	public Pagination(int currentPage,int total,String page,String path,Map<String,String> queryParams){
		this(currentPage, total,queryParams);
		if(null != page){
			config.page = page;
		}
		if(null != path){
			config.path = path;
		}
	}
	
	
	private List<T> items;
	
	/**
	 * 当前页数
	 */
	private int currentPage;
	
	/**
	 * 最后一页页码
	 */
	private int lastPage;
	
	/**
	 * 总记录数
	 */
	private int total;
	
	/**
	 * 默认每页5个
	 */
	private int pageSize = 10;
	
	private boolean hasMore;
	
	public List<T> getItems() {
		return items;
	}

	public void setItems(List<T> items) {
		this.items = items;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
		//这里根据pageSize重新计算分页个数及是否有下一页
		this.lastPage = total % pageSize == 0 ? total/pageSize : (total/pageSize + 1);
		this.hasMore = this.currentPage < this.lastPage;
	}

	/**
	 * 是否有分页
	 * @return
	 */
	private boolean hasPages(){
		return !(1 == this.currentPage && !this.hasMore);
	}
	
	/**
	 * 生成一个禁用的按钮
	 * @param text
	 * @return
	 */
	private String getDisabledTextWrapper(String text){
		return "<li class='disabled'><span>" + text + "</span></li>";
	}
	
	/**
	 * 生成一个激活的按钮
	 * @param text
	 * @return
	 */
	private String getActivePageWrapper(String text){
		return "<li class='active'><span>" + text + "</span></li>";
	}
	
	/**
	 * 生成省略号按钮
	 * @return
	 */
	private String getDots(){
		return this.getDisabledTextWrapper("...");
	}
	
	/**
	 * 生成一个可点击的按钮
	 * @param url
	 * @param page
	 * @return
	 */
	private String getAvailablePageWrapper(String url,String page){
		return "<li><a href='" +url + "'>" + page + "</a></li>";
	}
	
	/**
	 * 生成普通页码按钮
	 * @param url
	 * @param page
	 * @return
	 */
	private String getPageLinkWrapper(String url,String page){
		if(page.equals(String.valueOf(this.currentPage))){
			return this.getActivePageWrapper(page);
		}
		return this.getAvailablePageWrapper(url, page);
	}
	
	/**
	 * 批量生成页码按钮.
	 * @param urls
	 * @return
	 */
	private String getUrlLinks(Map<Integer,String> urls){
		StringBuilder builder = new StringBuilder("");
		
		if(null != urls && urls.size() > 0){
			for(Integer page : urls.keySet()){
				builder.append(this.getPageLinkWrapper(urls.get(page), String.valueOf(page)));
			}
		}
		return builder.toString();
	}
	
	/**
	 * 创建一组分页链接
	 * @param start
	 * @param end
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	private Map<Integer,String> getUrlRange(int start, int end) throws UnsupportedEncodingException{
		Map<Integer,String> urls = new HashMap<Integer,String>();
		for(int page = start;page<=end;page++){
			urls.put(page, this.getUrl(page));
		}
		return urls;
	}
	
	/**
	 * 获取页码对应的链接
	 * @param page
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	private String getUrl(int page) throws UnsupportedEncodingException{
		if(page<0){
			page = 1;
		}
		//组合查询参数
		StringBuilder urlBuilder = new StringBuilder();
		if(null != config.path){
			urlBuilder.append(config.path);
		}
		urlBuilder.append("?page=").append(page);
		if(config.queryParams.size() > 0){
			for(String param : config.queryParams.keySet()){
				urlBuilder.append("&").append(param).append("=").append(URLEncoder.encode(config.queryParams.get(param),"utf-8"));
			}
		}
		return urlBuilder.toString();
	}
	
	/**
     * 页码按钮
     * @return string
	 * @throws UnsupportedEncodingException 
     */
	private String getLinks() throws UnsupportedEncodingException{
		int size = 3;
		int window = size * 2;
		
		Map<Integer,String> first = null;
		Map<Integer,String> slide = null;
		Map<Integer,String> last = null;
		
		if(this.lastPage < window + 6){
			first = this.getUrlRange(1, this.lastPage);
		}else if(this.currentPage <= window){
			first = this.getUrlRange(1, window+2);
			last = this.getUrlRange(this.lastPage -1 , this.lastPage);
		}else if(this.currentPage > (this.lastPage - window)){
			first = this.getUrlRange(1, 2);
			last = this.getUrlRange(this.lastPage -(window+2) , this.lastPage);
		}else{
			first = this.getUrlRange(1, 2);
			slide = this.getUrlRange(this.currentPage - size, this.currentPage + size);
			last = this.getUrlRange(this.lastPage -1 , this.lastPage);
		}
		
		StringBuilder builder = new StringBuilder();
		
		if(first.size() > 0){
			builder.append(this.getUrlLinks(first));
		}
		
		if(null != slide && slide.size() > 0){
			builder.append(this.getDots());
			builder.append(this.getUrlLinks(slide));
		}
		
		if(null != last && last.size()>0){
			builder.append(this.getDots());
			builder.append(this.getUrlLinks(last));
		}
		
		return builder.toString();
				
	}
	/**
	 * 上一页按钮
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	private String getPreviousButton() throws UnsupportedEncodingException{
		String character = "&laquo;";
		
		if(this.currentPage <= 1){
			return this.getDisabledTextWrapper(character);
		}
		
		String url = this.getUrl(this.currentPage - 1);
		
		return this.getPageLinkWrapper(url, character);
	}
	
	/**
	 * 下一页按钮
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	private String getNextButton() throws UnsupportedEncodingException{
		
		String character = "&raquo;";
		
		if(!this.hasMore){
			return this.getDisabledTextWrapper(character);
		}
		
		String url=this.getUrl(this.currentPage + 1);
		
		return this.getPageLinkWrapper(url, character);
	}
	
	/**
	 * 渲染分页html
	 * @return
	 */
	public String getRender(){
		if(this.hasPages()){
			StringBuilder builder = new StringBuilder("<ul class='pagination'>");
			try{
				builder.append(this.getPreviousButton());
				builder.append(this.getLinks());
				builder.append(this.getNextButton());
			}
			catch(UnsupportedEncodingException e){
				e.printStackTrace();
			}
			builder.append("</ul>");
			return builder.toString();
		}
		return null;
	}
	
}
